home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
SNNSV32.ZIP
/
SNNSv3.2
/
kernel
/
sources
/
kr_JordElm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-25
|
14KB
|
497 lines
/*****************************************************************************
FILE : kr_JordElm.c
SHORTNAME : kr_JordElm.c
SNNS VERSION : 3.2
PURPOSE : Topological sorting for Jordan and Elman networks
NOTES :
AUTHOR : Tobias Soyez
DATE : 09.11.1993
CHANGED BY :
IDENTIFICATION : @(#)kr_JordElm.c 1.2 3/15/94
SCCS VERSION : 1.2
LAST CHANGE : 3/15/94
Copyright (c) 1990-1994 SNNS Group, IPVR, Univ. Stuttgart, FRG
******************************************************************************/
#include "kr_typ.h"
#include "kr_const.h"
#include "kr_def.h"
#include "kr_mac.h"
#include "kernel.h"
#include "kr_JordElm.ph"
/*****************************************************************************
FUNCTION : kr_recTouchContextUnits
PURPOSE : touches only context units recursively
NOTES :
RETURNS :
UPDATE :
******************************************************************************/
static void kr_recTouchContextUnits (struct Unit *unit_ptr)
{
struct Site *site_ptr ;
struct Link *link_ptr ;
bool unit_has_incoming_links ;
if (unit_ptr->flags & UFLAG_REFRESH) return ;
if ((IS_HIDDEN_UNIT (unit_ptr)) && (IS_SPECIAL_UNIT (unit_ptr)))
{
/* ----------- touch only context units ------------- */
unit_ptr->flags |= UFLAG_REFRESH ; /* set the 'touch' flag */
unit_has_incoming_links = FALSE ;
switch (unit_ptr->flags & UFLAG_INPUT_PAT)
{
case UFLAG_DLINKS: /* unit has direct links */
FOR_ALL_LINKS (unit_ptr, link_ptr)
{
kr_recTouchContextUnits (link_ptr->to) ;
unit_has_incoming_links = TRUE ;
}
break ;
case UFLAG_SITES: /* unit has sites */
FOR_ALL_SITES_AND_LINKS (unit_ptr, site_ptr, link_ptr)
{
kr_recTouchContextUnits (link_ptr->to) ;
unit_has_incoming_links = TRUE ;
}
break ;
}
}
if ((! unit_has_incoming_links) && (! IS_INPUT_UNIT (unit_ptr)))
{
/* unit has no incoming links -> dead unit -> delete touch flag */
unit_ptr->flags &= ~UFLAG_REFRESH ;
}
}
/*****************************************************************************
FUNCTION : kr_recTopoCheckJE
PURPOSE : recursive topology check, called by kr_topoCheckJE
NOTES :
RETURNS :
UPDATE :
******************************************************************************/
static void kr_recTopoCheckJE (struct Unit *unit_ptr, int depth)
{
struct Site *site_ptr ;
struct Link *link_ptr ;
bool unit_has_incoming_links ;
if ((IS_HIDDEN_UNIT (unit_ptr)) && (IS_SPECIAL_UNIT (unit_ptr)))
{
/* -------- touch context units recursively -------- */
kr_recTouchContextUnits (unit_ptr) ;
return ;
}
if (unit_ptr->flags & UFLAG_REFRESH)
{
if (unit_ptr->lln == 0)
{
/* logical layer no. isn't set => Cycle found */
topo_msg.no_of_cycles++ ;
if (topo_msg.error_code == KRERR_NO_ERROR)
{
topo_msg.src_error_unit = unit_ptr - unit_array ;
topo_msg.error_code = KRERR_CYCLES ;
}
}
return ;
}
/* ----- unit is not a context unit and has not been touched yet ------ */
/* ----- continue recursive depth search ------ */
unit_ptr->flags |= UFLAG_REFRESH ; /* set the 'touch' flag */
unit_has_incoming_links = FALSE ;
switch (unit_ptr->flags & UFLAG_INPUT_PAT)
{
case UFLAG_DLINKS: /* unit has direct links */
FOR_ALL_LINKS (unit_ptr, link_ptr)
{
kr_recTopoCheckJE (link_ptr->to, depth + 1) ;
unit_has_incoming_links = TRUE ;
}
break ;
case UFLAG_SITES: /* unit has sites */
FOR_ALL_SITES_AND_LINKS (unit_ptr, site_ptr, link_ptr)
{
kr_recTopoCheckJE (link_ptr->to, depth + 1) ;
unit_has_incoming_links = TRUE ;
}
break ;
}
/* remember the depth (for cycle detection and statistics) */
unit_ptr->lln = depth ;
/* store highest layer no. */
if (depth > topo_msg.no_of_layers) topo_msg.no_of_layers = depth ;
if ((! unit_has_incoming_links) && (! IS_INPUT_UNIT (unit_ptr)))
{
/* unit has no incoming links -> dead unit -> delete touch flag */
unit_ptr->flags &= ~UFLAG_REFRESH ;
}
}
/*****************************************************************************
FUNCTION : kr_topoCheckJE
PURPOSE : Checks the topology of partial recurrent networks
(i.e. JORDAN or ELMAN networks) :
only recurrent links to context units are allowed
NOTES :
RETURNS : kernel error code
UPDATE :
******************************************************************************/
krui_err kr_topoCheckJE (void)
{
struct Unit *unit_ptr ;
bool o_units ;
topo_msg.no_of_cycles =
topo_msg.no_of_dead_units =
topo_msg.dest_error_unit =
topo_msg.src_error_unit =
topo_msg.no_of_layers = 0 ;
topo_msg.error_code = KernelErrorCode = KRERR_NO_ERROR ;
if (NoOfUnits == 0)
{
/* no units defined */
KernelErrorCode = KRERR_NO_UNITS ;
return (KernelErrorCode) ;
}
/* ------------------- reset units 'touch' flags ----------------------- */
FOR_ALL_UNITS (unit_ptr)
if (UNIT_IN_USE (unit_ptr))
{
unit_ptr->flags &= ~UFLAG_REFRESH ;
unit_ptr->lln = 0 ;
}
/* ---------- begin depth search at the first output unit -------------- */
o_units = FALSE ;
FOR_ALL_UNITS (unit_ptr)
if (IS_OUTPUT_UNIT (unit_ptr) && UNIT_IN_USE (unit_ptr))
{
o_units = TRUE ;
kr_recTopoCheckJE (unit_ptr, 1) ;
if (topo_msg.error_code != KRERR_NO_ERROR)
{ /* stop if an error occured */
KernelErrorCode = topo_msg.error_code ;
return (KernelErrorCode) ;
}
}
if (!o_units)
{ /* no output units */
KernelErrorCode = KRERR_NO_OUTPUT_UNITS ;
return (KernelErrorCode) ;
}
/* ---------- search for dead units i.e. units without inputs ---------- */
FOR_ALL_UNITS (unit_ptr)
if (!(unit_ptr->flags & UFLAG_REFRESH) && UNIT_IN_USE (unit_ptr))
{
topo_msg.error_code = KRERR_DEAD_UNITS ;
topo_msg.no_of_dead_units++ ;
if (topo_msg.src_error_unit == 0)
topo_msg.src_error_unit = unit_ptr - unit_array ;
}
if (topo_msg.no_of_dead_units != 0)
KernelErrorCode = KRERR_DEAD_UNITS ;
return (topo_msg.error_code) ;
}
/*****************************************************************************
FUNCTION : kr_recTopoSortJE
PURPOSE : stores only hidden (NOT special hidden !) units in the topologic
array
NOTES :
RETURNS :
UPDATE :
******************************************************************************/
static void kr_recTopoSortJE (struct Unit *unit_ptr, int depth)
{
struct Site *site_ptr ;
struct Link *link_ptr ;
/* --------------------- ignore context units ------------------------- */
if ((IS_HIDDEN_UNIT (unit_ptr)) && (IS_SPECIAL_UNIT (unit_ptr)))
{
unit_ptr->flags |= UFLAG_REFRESH ; /* set the 'touch' flag */
return ;
}
if (unit_ptr->flags & UFLAG_REFRESH)
{
/* the 'touch' flag is set: don't continue search */
topo_msg.src_error_unit = unit_ptr - unit_array ; /* store unit number */
if IS_OUTPUT_UNIT (unit_ptr)
{
/* this output unit has a output connection to another unit */
if (topo_msg.error_code == KRERR_NO_ERROR)
topo_msg.error_code = KRERR_O_UNITS_CONNECT ;
}
else
if (unit_ptr->lln == 0)
{
/* logical layer no. isn't set => Cycle found */
topo_msg.no_of_cycles++ ;
if (topo_msg.error_code == KRERR_NO_ERROR)
topo_msg.error_code = KRERR_CYCLES ;
}
return ;
}
else
unit_ptr->flags |= UFLAG_REFRESH ; /* set the 'touch' flag */
/* ------------------------- continue search -------------------------- */
switch (unit_ptr->flags & UFLAG_INPUT_PAT)
{
case UFLAG_DLINKS:
FOR_ALL_LINKS (unit_ptr, link_ptr)
kr_recTopoSortJE (link_ptr->to, depth + 1) ;
break ;
case UFLAG_SITES:
FOR_ALL_SITES_AND_LINKS (unit_ptr, site_ptr, link_ptr)
kr_recTopoSortJE (link_ptr->to, depth + 1) ;
break ;
}
/* remember the depth (for cycle detection and statistics) */
unit_ptr->lln = depth ;
/* ------------------------ store hidden units ------------------------ */
if IS_HIDDEN_UNIT( unit_ptr )
{
*topo_ptr++ = unit_ptr ;
no_of_topo_units++ ;
}
}
/*****************************************************************************
FUNCTION : kr_topoSortJE
PURPOSE : sorts units of a partial recurrent network by their topologic
type input, hidden, output, context and stores the pointers to
this units in the topologic array
NOTES : ########### V E R Y I M P O R T A N T N O T E ############
no_of_topo_units contains only the number of input, hidden and
output units
no_of_topo_units DOES NOT contain the no. of context units !!!
all special hidden units (io-type = SPECIAL_H) are assumed to
be context units
!! before calling this function: !!
!! check the network topology with kr_topoCheckJE !!
RETURNS : error code
UPDATE :
******************************************************************************/
krui_err kr_topoSortJE (void)
{
int i ;
register struct Unit *unit_ptr ;
KernelErrorCode = KRERR_NO_ERROR ; /* reset return code */
topo_ptr = topo_ptr_array ; /* initialize global pointer */
NoOfInputUnits = 0 ;
NoOfOutputUnits = 0 ;
no_of_topo_units = 0 ;
*topo_ptr++ = NULL ; /* limit left side of the topological */
/* array with NULL pointer */
/* ------------------ reset 'touch' flags of all units ----------------- */
FOR_ALL_UNITS (unit_ptr)
if (UNIT_IN_USE (unit_ptr))
{
unit_ptr->flags &= ~UFLAG_REFRESH ;
unit_ptr->lln = 0 ;
}
/* ----------- store all input units in the topologic array ------------ */
FOR_ALL_UNITS (unit_ptr)
if (IS_INPUT_UNIT (unit_ptr) && UNIT_IN_USE (unit_ptr))
{
if UNIT_HAS_INPUTS (unit_ptr)
{
/* links to input units are not allowed */
topo_msg.dest_error_unit = unit_ptr - unit_array ;
KernelErrorCode = KRERR_I_UNITS_CONNECT ;
return (KernelErrorCode) ;
}
NoOfInputUnits++ ;
no_of_topo_units++ ;
*topo_ptr++ = unit_ptr ;
}
*topo_ptr++ = NULL ; /* limit input units in the topological array with */
/* NULL pointer */
if (NoOfInputUnits == 0)
{
KernelErrorCode = KRERR_NO_INPUT_UNITS ;
return( KernelErrorCode ) ;
}
/* ----------- store all hidden units in the topologic array ----------- */
/* sorts hidden units by their topological order using recursive depth */
/* search starting at the first output unit */
FOR_ALL_UNITS( unit_ptr )
if (IS_OUTPUT_UNIT (unit_ptr) && UNIT_IN_USE (unit_ptr))
{
kr_recTopoSortJE (unit_ptr, 1) ;
if (topo_msg.error_code != KRERR_NO_ERROR)
{
KernelErrorCode = topo_msg.error_code ;
return (KernelErrorCode) ;
}
}
*topo_ptr++ = NULL ; /* limit hidden units in the topological array with */
/* NULL pointer */
/* ----------- store all output units in the topologic array ----------- */
FOR_ALL_UNITS (unit_ptr)
if (IS_OUTPUT_UNIT (unit_ptr) && UNIT_IN_USE (unit_ptr))
{
NoOfOutputUnits++ ;
no_of_topo_units++ ;
*topo_ptr++ = unit_ptr ;
}
if (NoOfOutputUnits == 0)
{
KernelErrorCode = KRERR_NO_OUTPUT_UNITS ;
return (KernelErrorCode) ;
}
*topo_ptr++ = NULL ; /* limit output units in the topological array with */
/* NULL pointer */
/* ---------- store all context units in the topologic array ----------- */
/* !!! no_of_topo_units MUST NOT BE INCREMENTED ANY MORE !!! */
FOR_ALL_UNITS (unit_ptr)
if (IS_HIDDEN_UNIT (unit_ptr) && IS_SPECIAL_UNIT (unit_ptr) &&
UNIT_IN_USE (unit_ptr))
{
*topo_ptr++ = unit_ptr ;
}
*topo_ptr++ = NULL ; /* limit context units in the topological array with */
/* NULL pointer */
/* --------- search for dead units i.e. units without inputs ----------- */
FOR_ALL_UNITS (unit_ptr)
if (!(unit_ptr->flags & UFLAG_REFRESH) && UNIT_IN_USE (unit_ptr))
{
topo_msg.no_of_dead_units++ ;
if (topo_msg.src_error_unit == 0)
topo_msg.src_error_unit = unit_ptr - unit_array ;
}
if (topo_msg.no_of_dead_units != 0) KernelErrorCode = KRERR_DEAD_UNITS ;
return( KernelErrorCode ) ;
}
/*****************************************************************************
E N D O F F I L E
******************************************************************************/